
/*
 * Quixie String 0.2 <quixie_string.h>
 * Mj Mendoza IV <mjmendoza@konsolscript.org>
 * A small collection of String-related functions for use of libQuixie.
 *
 * TODO: Move logics to quixie_string.c, have this to contain prototypes instead.
 */

/**
 * This are simple wrappers for code-readability.
 **/
#define quixie_string_get_length(s) ((int) strlen(s))
#define quixie_string_allocate(n) ((char *) malloc(sizeof(char) * (n + 1)))
 
/**
 * This is a simple wrapper to make sure that quixie_string_append() is used properly.
 **/
char *quixie_string_new() {
	char *tmp = quixie_string_allocate(0);
		strcpy(tmp, "");
	return tmp;
}

/**
 * WARNING: This could be prone to memory leak if s1 is not initialized with malloc
 * This makes sure that s1 could allocate values to be copied from s2.
 * char *s1   s1 SHOULD HAVE been initialized with quixie_string_new()
 * char *s2   chars that will replace chars in s1
 * returns the new char pointer chars from s2; chars from s1 is now deleted.
 **/
void quixie_string_set(char **s1, char *s2) {
	/*
		Free the pointer where s1 is previously residing to put s1's pointer
		to a place where it could allocate longer string value.
	*/
	free(s1);
	*s1 = quixie_string_allocate(quixie_string_get_length(s2));
		strcpy(*s1, s2);
}

/**
 * WARNING: This could be prone to memory leak if s1 is not initialized with malloc
 * This makes sure that s1 could allocate values to be concatenated from s2.
 * char *s1   s1 SHOULD HAVE been initialized with quixie_string_new()
 * char *s2   chars that will join to s1
 * returns the new char pointer where chars from s1 and s2 are connected as one string.
 **/
void quixie_string_append(char **s1, char *s2) {
	char *tmp1 = *s1;
	char *tmp2 = quixie_string_allocate(quixie_string_get_length(*s1) + quixie_string_get_length(s2));
		strcpy(tmp2, "");
			strcat(tmp2, tmp1);
			strcat(tmp2, s2);
	
	quixie_string_set(s1, tmp2);
		free(tmp2);
}

/**
 * WARNING: This could be prone to memory leak if s1 is not initialized with malloc
 * Returns a character from s1 in a string format.
 *  ex: quixie_string_char_at("hello", ret, 1) //<-- will give "e" to ret instead of 'e'
 * char *s1   contains the string value which a character (specified by index) will be extracted
 * char *s2   will hold a string value of the character from s1
 * int index  which character from s1 will it be
 * returns the character on s1's indicated index, or space. //<-- still have to decide in using null-string (not null pointer) instead.
 **/
char *quixie_string_char_at(char *s1, char *s2, int index) {
	char tmp[2];
	char *tmpb;
	int tmplen = quixie_string_get_length(s1);
	
	if (index < tmplen) {
		if (index < 0) {
			if ((tmplen + index) < tmplen) {
				tmp[0] = s1[tmplen + index];
			} else {
				tmp[0] = ' ';
			}
		} else {
			tmp[0] = s1[index];
		}
	} else {
		tmp[0] = ' ';
	}
	tmp[1] = '\0';
		tmpb = tmp;
			quixie_string_set(&s2, tmpb);
			return s2;
}

/**
 * Checks whether sValue is in the following format:
 *  - 123456
 *  - 123.456
 *  - -0.12345 (negative value)
 *  - 0x123456 (hexadecimal format that KonsolScript understands)
 * char *sValue   a string value to be check of numeric format
 * returns 1 if string format is a numeric value that is understood by KonsolScript, 0 otherwise.
 **/
int quixie_string_is_numeric(char *sValue) {
	int bGotDOT = 0;
	char *tmp = quixie_string_new();
	int tmplen = quixie_string_get_length(sValue);
	int i;
	for (i = 0; i < tmplen; i++) {
		tmp = quixie_string_char_at(sValue, tmp, i);
		if (tmp[0] >= 48 && tmp[0] <= 57) { //is character from '0' to '9'
			//okay
		} else if (strcmp(tmp, "-") == 0) {
			if (i > 1 || tmplen == 1) return 0;
		} else if (strcmp(tmp, ".") == 0) {
			if (bGotDOT == 0 && tmplen > 1) {
				bGotDOT = 1;
			} else {
				//can't have a value of "1.2.3"
				//can't have a value of "." alone
				return 0;
			}
		} else {
			return 0;
		}
	}
	
	return 1;
}
